package com.sc.base.common.spring.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import redis.clients.jedis.JedisPoolConfig;

public class RedisConfiguration {

    @Value("${spring.redis.sentinel.master:mymaster}")
    public String master;

    @Value("${spring.redis.password:123456}")
    public String password;

    @Value("${spring.redis.database:1}")
    public Integer database;

    @Value("${spring.redis.sentinel.nodes:127.0.0.1:26379}")
    public String nodes;

    @Value("${spring.redis.pool.max-active}")
    private int maxActive;

    @Value("${spring.redis.pool.max-idle}")
    private int maxIdle;
    @Value("${spring.redis.pool.min-idle}")
    private int minIdle;
    @Value("${spring.redis.pool.max-wait}")
    private long maxWait;


    @Primary
    @Bean
    public JedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
        RedisSentinelConfiguration redisSentinelConfiguration =  new RedisSentinelConfiguration();
        redisSentinelConfiguration.setMaster(master);
        redisSentinelConfiguration.setDatabase(database);
        redisSentinelConfiguration.setPassword(RedisPassword.of(password));
        if(nodes.contains(",")){
            String[] sentinel= nodes.split(",");
            for(String hostandport:sentinel){
                RedisNode redisNode = readHostAndPortFromString(hostandport);
                redisSentinelConfiguration.addSentinel(redisNode);
            }
        }else{
            String[] args = StringUtils.split(nodes, ":");
            redisSentinelConfiguration.sentinel(args[0],Integer.getInteger(args[1],26379));
        }
        return new JedisConnectionFactory(redisSentinelConfiguration,jedisPoolConfig);
    }


    @Primary
    @Bean("jedisPoolConfig")
    public JedisPoolConfig getJedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //连接耗尽时是否阻塞, false报异常,true阻塞直到超时, 默认true
        jedisPoolConfig.setBlockWhenExhausted(true);
        //在空闲时检查有效性, 默认false
        jedisPoolConfig.setTestWhileIdle(true);
        //获取连接是检查有效性
        jedisPoolConfig.setTestOnBorrow(true);
        //最大连接数
        jedisPoolConfig.setMaxTotal(maxActive);
        //对象空闲多久后逐出, 当空闲时间>该值 且 空闲连接>最大空闲数 时直接逐出,不再根据MinEvictableIdleTimeMillis判断  (默认逐出策略)
        jedisPoolConfig.setSoftMinEvictableIdleTimeMillis(1800000);
        //最大空闲连接数, 默认8个
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setBlockWhenExhausted(true);
        //最小空闲连接数, 默认0
        jedisPoolConfig.setMinIdle(minIdle);
        //逐出连接的最小空闲时间 默认1800000毫秒(15分钟)
        jedisPoolConfig.setTimeBetweenEvictionRunsMillis(900000);
        //获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,  默认-1
        jedisPoolConfig.setMaxWaitMillis(maxWait);
        return jedisPoolConfig;
    }

    private RedisNode readHostAndPortFromString(String hostAndPort) {
        String[] args = StringUtils.split(hostAndPort, ":");
        Assert.notNull(args, "HostAndPort need to be seperated by  ':'.");
        Assert.isTrue(args.length == 2, "Host and Port String needs to specified as host:port");
        return new RedisNode(args[0], Integer.valueOf(args[1]));
    }

}
